<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * This file contains the PDODB_Connection_Exception class and its subclasses.
 *
 * This file contains the following classes:
 *
 * <ul>
 * <li>PDODB_Connection_Exception</li>
 * <li>PDODB_SyntaxException</li>
 * <li>PDODB_NotFoundException</li>
 * <li>PDODB_AlreadyExistsException</li>
 * <li>PDODB_TruncatedException</li>
 * <li>PDODB_InvalidException</li>
 * <li>PDODB_InvalidNumberException</li>
 * <li>PDODB_DivisionByZeroException</li>
 * <li>PDODB_CannotCreateException</li>
 * <li>PDODB_CannotDeleteException</li>
 * <li>PDODB_CannotDropException</li>
 * <li>PDODB_CannotAlterException</li>
 * <li>PDODB_CannotReplaceException</li>
 * <li>PDODB_NoDatabaseSelectedException</li>
 * <li>PDODB_NoSuchDatabaseException</li>
 * <li>PDODB_NoSuchTableException</li>
 * <li>PDODB_NoSuchColumnException</li>
 * <li>PDODB_NotLockedException</li>
 * <li>PDODB_AccessViolationException</li>
 * <li>PDODB_ConstraintException</li>
 * <li>PDODB_ConstraintNotNullException</li>
 * <li>PDODB_DeadlockException</li>
 * </ul>
 *
 * PHP version 5
 *
 * This file is part of PEAR::PDODB - A database abstraction layer for PHP5 built
 * using PDO. PHP version 5.1+ is recommended.
 *
 * PEAR::PDODB is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * PEAR::PDODB is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with PEAR::PDODB. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package     PDODB
 * @category    Database
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright   2007 Michael J. I. Jackson
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
 * @version     SVN: $Id: Exception.php 2 2007-11-27 17:20:29Z mjijackson $
 * @link        http://pear.php.net/packages/PDODB
 */

/**
 * Require PDODB_Exception
 */
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Exception.php';

/**
 * The base class for all exceptions thrown by PDODB_Connection that were caused
 * by exceptions originally thrown by PDO.
 *
 * @package     PDODB
 * @category    Database
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @see         PDODB_Exception
 */
class PDODB_Connection_Exception extends PDODB_Exception
{

    protected $sql;

    /**
     * Constructor. The error code is optional and will automatically be
     * resolved if not provided.
     *
     * @param   string          $message    The error message to use
     * @param   PDOException    $e          The original exception
     * @param   string          $sql        The SQL query that generated the
     *                                      exception
     * @param   int             $code       The common PDODB::E_* error code
     *                                      constant for this exception
     * @access  public
     */
    public function __construct($message, PDOException $e, $sql, $code = null)
    {
        $this->sql = $sql;
        if (is_null($code)) {
            $code = self::getCodeFor($this);
        }

        parent::__construct($message, $e, $code);
    }

    /**
     * Gets the SQL that triggered this exception.
     *
     * @return  string          The SQL that triggered this exception
     * @access  public
     */
    public function getSQL()
    {
        return $this->sql;
    }

    /**
     * Gets the SQLSTATE error code associated with this exception.
     *
     * @return  string          The SQLSTATE error code
     * @access  public
     */
    public function getSQLState()
    {
        return $this->getCause()->getCode();
    }

    private static $e_map = array(
        PDODB::E_UNKNOWN                => 'PDODB_Connection_Exception',
        PDODB::E_SYNTAX                 => 'PDODB_SyntaxException',
        PDODB::E_NOT_FOUND              => 'PDODB_NotFoundException',
        PDODB::E_ALREADY_EXISTS         => 'PDODB_AlreadyExistsException',
        PDODB::E_TRUNCATED              => 'PDODB_TruncatedException',
        PDODB::E_INVALID                => 'PDODB_InvalidException',
        PDODB::E_INVALID_NUMBER         => 'PDODB_InvalidNumberException',
        PDODB::E_DIVZERO                => 'PDODB_DivisionByZeroException',
        PDODB::E_CANNOT_CREATE          => 'PDODB_CannotCreateException',
        PDODB::E_CANNOT_DELETE          => 'PDODB_CannotDeleteException',
        PDODB::E_CANNOT_DROP            => 'PDODB_CannotDropException',
        PDODB::E_CANNOT_ALTER           => 'PDODB_CannotAlterException',
        PDODB::E_CANNOT_REPLACE         => 'PDODB_CannotReplaceException',
        PDODB::E_NODBSELECTED           => 'PDODB_NoDatabaseSelectedException',
        PDODB::E_NOSUCHDB               => 'PDODB_NoSuchDatabaseException',
        PDODB::E_NOSUCHTABLE            => 'PDODB_NoSuchTableException',
        PDODB::E_NOSUCHCOLUMN           => 'PDODB_NoSuchColumnException',
        PDODB::E_NOT_LOCKED             => 'PDODB_NotLockedException',
        PDODB::E_ACCESS_VIOLATION       => 'PDODB_AccessViolationException',
        PDODB::E_CONSTRAINT             => 'PDODB_ConstraintException',
        PDODB::E_CONSTRAINT_NOT_NULL    => 'PDODB_ConstraintNotNullException',
        PDODB::E_DEADLOCK               => 'PDODB_DeadlockException'
    );

    private static $e_msgs = array(
        PDODB::E_UNKNOWN                => 'Unknown error',
        PDODB::E_SYNTAX                 => 'Syntax error',
        PDODB::E_NOT_FOUND              => 'Not found',
        PDODB::E_ALREADY_EXISTS         => 'Already exists',
        PDODB::E_TRUNCATED              => 'Truncated literal',
        PDODB::E_INVALID                => 'Invalid',
        PDODB::E_INVALID_NUMBER         => 'Invalid number',
        PDODB::E_DIVZERO                => 'Division by zero',
        PDODB::E_CANNOT_CREATE          => 'Cannot create',
        PDODB::E_CANNOT_DELETE          => 'Cannot delete',
        PDODB::E_CANNOT_DROP            => 'Cannot drop',
        PDODB::E_CANNOT_ALTER           => 'Cannot alter',
        PDODB::E_CANNOT_REPLACE         => 'Cannot replace',
        PDODB::E_NODBSELECTED           => 'No database selected',
        PDODB::E_NOSUCHDB               => 'No such database',
        PDODB::E_NOSUCHTABLE            => 'No such table',
        PDODB::E_NOSUCHCOLUMN           => 'No such column',
        PDODB::E_NOT_LOCKED             => 'Unable to obtain a lock',
        PDODB::E_ACCESS_VIOLATION       => 'Access violation',
        PDODB::E_CONSTRAINT             => 'Constraint error',
        PDODB::E_CONSTRAINT_NOT_NULL    => 'Constraint not null',
        PDODB::E_DEADLOCK               => 'Deadlock error'
    );

    /**
     * Wraps PDOExceptions in the proper subclass of PDODB_Connection_Exception and
     * generates a new instance of that class.
     *
     * @param   int             $code   The common PDODB error code
     * @param   PDOException    $e      The original exception
     * @param   string          $sql    The SQL query that generated the
     *                                  exception
     * @return  PDODB_Connection_Exception   A newly generated PDODB_Connection_Exception
     * @access  public
     * @static
     */
    public static function factory($code, PDOException $e, $sql = null)
    {
        $e_class = self::$e_map[$code];
        $message = self::$e_msgs[$code] . ' (' . $e->getMessage() . ')';
        return new $e_class($message, $e, $sql, $code);
    }

    /**
     * Gets the appropriate PDODB error code for the given exception.
     *
     * @param   PDODB_Connection_Exception   $e  The exception to get the code for
     * @access  public
     * @static
     */
    public static function getCodeFor(PDODB_Connection_Exception $e)
    {
        $code = array_search(get_class($e), self::$e_map);
        return ($code === false) ? PDODB::E_UNKNOWN : $code;
    }

}

/**
 * Syntax exception. Thrown when there is an error in the SQL syntax.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_SyntaxException extends PDODB_Connection_Exception {}

/**
 * Not found exception. Thrown when the query refers to a non-existent object.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_NotFoundException extends PDODB_Connection_Exception {}

/**
 * Already exists exception. Thrown when the query is trying to create a
 * duplicate object.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_AlreadyExistsException extends PDODB_Connection_Exception {}

/**
 * Truncated exception. Thrown when a submitted literal value was too long and
 * needed to be truncated.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_TruncatedException extends PDODB_Connection_Exception {}

/**
 * Invalid exception. Thrown when a literal value does not match the
 * expected data type.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_InvalidException extends PDODB_Connection_Exception {}

/**
 * Invalid number exception. Thrown when the supplied value is not a valid
 * number.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_InvalidNumberException extends PDODB_Connection_Exception {}

/**
 * Division by zero exception. Thrown when the query requires division by zero.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_DivisionByZeroException extends PDODB_Connection_Exception {}

/**
 * Cannot create exception. Thrown when the DBMS is unable to create the
 * requested object.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_CannotCreateException extends PDODB_Connection_Exception {}

/**
 * Cannot delete exception. Thrown when the DBMS is unable to delete the
 * specified object.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_CannotDeleteException extends PDODB_Connection_Exception {}

/**
 * Cannot drop exception. Thrown when the DBMS is unable to drop the specified
 * object.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_CannotDropException extends PDODB_Connection_Exception {}

/**
 * Cannot alter exception. Thrown when the DBMS cannot perform the specified
 * alterations.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_CannotAlterException extends PDODB_Connection_Exception {}

/**
 * Cannot replace exception. Thrown when the DBMS cannot perform the desired
 * REPLACE query.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_CannotReplaceException extends PDODB_Connection_Exception {}

/**
 * No database selected exception. Thrown when no database is selected.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_NoDatabaseSelectedException extends PDODB_Connection_Exception {}

/**
 * No such database exception. Thrown when the requested database does not
 * exist.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_NoSuchDatabaseException extends PDODB_Connection_Exception {}

/**
 * No such table exception. Thrown when the requested table does not exist.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_NoSuchTableException extends PDODB_Connection_Exception {}

/**
 * No such column exception. Thrown when the requested column does not exist.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_NoSuchColumnException extends PDODB_Connection_Exception {}

/**
 * Not locked exception. Thrown when the requested table lock cannot be
 * obtained.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_NotLockedException extends PDODB_Connection_Exception {}

/**
 * Access violation exception. Thrown when the database user does not have
 * sufficient privileges to perform the requested operations.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_AccessViolationException extends PDODB_Connection_Exception {}

/**
 * Constraint exception. Thrown when the query does not satisfy a table
 * constraint.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_ConstraintException extends PDODB_Connection_Exception {}

/**
 * Constraint not null exception. Thrown when a NOT NULL column constraint is
 * given a NULL value.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_ConstraintNotNullException extends PDODB_Connection_Exception {}

/**
 * Deadlock exception. Thrown when the DBMS encounters deadlock.
 *
 * @package     PDODB
 * @see         PDODB_Connection_Exception
 */
class PDODB_DeadlockException extends PDODB_Connection_Exception {}

?>
